#include "stdTcpService.h"
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <cstring>
#include <stdio.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <iostream>
#include <arpa/inet.h>


void StdTcpServer::setListen(int port)
{
     /*创建通信文件描述符*/
    int sockfd =socket(AF_INET,SOCK_STREAM,0);
    if(sockfd == -1)
    {
        perror("socket create error");
        _exit(-1);
    }
    /*设置地址复用*/
    int optval = 1;//开启地址复用
   int ret = setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&optval,sizeof(optval));
    if(ret == -1)
    {
        perror("setsockopt error:");
        _exit(-1);
    }
    /*绑定服务器的ip和端口信息*/
    sockaddr_in localAddress;
    /*清除脏数据*/
    memset(&localAddress,0,sizeof(localAddress));
    /*地址族*/
    localAddress.sin_family = AF_INET;//ipv4
    localAddress.sin_port= htons(port); //端口号
    localAddress.sin_addr.s_addr=htonl(INADDR_ANY); //全通：全0-
    /*绑定*/
    ret =bind(sockfd,(const sockaddr*)&localAddress,sizeof(localAddress));
    if(ret == -1)
    {
        perror("bind error:");
        _exit(-1);
    }
    /*监听*/
    ret = listen(sockfd,10);
    if(ret == -1)
    {
        perror("listen error:");
        _exit(-1);
    }
    /*维护一下端口属性*/
    m_port = port;
    /*维护一下通信句柄*/
    m_sockfd = sockfd;

}
StdTcpSocket * StdTcpServer::getClientSock()
{
    /*阻塞接受客户端的连接*/
    int connfd = accept(m_sockfd,NULL,NULL);
    if(connfd == -1)
    {
        perror("accept error:");
        _exit(-1);
    }
    std::cout<<"有新客户连接"<< connfd<<std::endl;
    StdTcpSocket * clientSock = new StdTcpSocket;
    clientSock->setConnfdAttr(connfd);
    return clientSock;
}
   
   /*连接服务器*/
bool StdTcpSocket::connectToServer(const char* ip, int port)
{
     /*创建通信文件描述符*/
    int sockfd =socket(AF_INET,SOCK_STREAM,0);
    if(sockfd == -1)
    {
        perror("socket create error");
        return false;
    }
    /*连接服务器*/
    sockaddr_in serverAddress;
    /*地址族-IPV4*/
    serverAddress.sin_family = AF_INET;
    /*端口*/
    serverAddress.sin_port = htons(port);
    /*服务器IP地址*/
    const char* serverIP = "192.168.87.128";
    inet_pton(AF_INET,serverIP,&(serverAddress.sin_addr.s_addr));
    /*连接服务器*/
    int ret =connect(sockfd,(const sockaddr*)&serverAddress,sizeof(serverAddress));
    if(ret == -1)
    {
        perror("connect error:");
        return false;
    }
    /*维护套接字句柄*/
    m_connfd = sockfd;
    return true;

}
void StdTcpSocket::setConnfdAttr(int connfd)
{
    this->m_connfd = connfd;
}
/*发送数据*/
int StdTcpSocket::sendMessage(const void *sendMsg, size_t size)
{
    /*发送数据大小*/
    write(m_connfd, &size, sizeof(size_t));
    /*发送数据本身*/
    int writeBytes = write(m_connfd, sendMsg, size);
    if (writeBytes < 0)
    {
        perror("send message error:");
        return -1;
    }
    return writeBytes;
   }
   /*发送数据*/
   int StdTcpSocket::sendMessage(const std::string& sendMsg)
   {
       return sendMessage(sendMsg.c_str(),sendMsg.size());
   }
   /*接收数据*/
   int StdTcpSocket::recvMessage(void *buf,size_t size)
   {
       return 0;
   }
   /*接收数据*/
   int StdTcpSocket::recvMessage(std::string& recvMeaasge)
   {
       /*1.先得到数据包的大小*/
       size_t dataSize = 0;
       int readBytes = read(m_connfd,&dataSize,sizeof(size_t));
            if(readBytes < 0)
       {
           perror("read error:");
           return readBytes;
       }
       /*2.再获取数据包本身*/
       char* msg = new char[dataSize + 1];
       if(msg == nullptr)
       {
           std::cout<<"malloc error"<<std::endl;
           return -1;
       }
       /*清除脏数据*/
       memset(msg,0,sizeof(char) * (dataSize + 1));
       size_t totalReceived =0;
       readBytes = 0;
    while(totalReceived < dataSize)
       {
        /*读到的字节数,可能上次没读完*/
            readBytes = read(m_connfd, msg+totalReceived, dataSize-totalReceived);
            if(readBytes < 0)
            {
                perror("read error:");
                delete[] msg;
                return readBytes;
            }else if(readBytes == 0)
            {
                delete[] msg;
                return readBytes;
            }
            totalReceived += readBytes;
       }
       /*赋值*/
       recvMeaasge = msg;
       /*释放堆空间*/
       delete[] msg;
       return dataSize;
     }